﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;

namespace INF1010_Chat
{
    public class User
    {
        public delegate void SomethingReceivedEventHandler(object sender, EventArgs args);
        public event SomethingReceivedEventHandler SomethingReceived;

        private string name;
        private GroupList groups;
        private Socket communicationSocket;
        private Thread threadReceive;
        private Queue<string> messages;

        private User()
        {
        }

        public User(string name)
        {
            this.name = name;
            messages = new Queue<string>();
            this.groups = new GroupList();
            this.communicationSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            threadReceive = new Thread(Receive);
        }

        public User(Socket communicationSocket)
        {
            this.communicationSocket = communicationSocket;
            messages = new Queue<string>();
            threadReceive = new Thread(Receive);
        }

        public string Name
        {
            get
            {
                return name;
            }
        }

        public bool IsAuthenticated
        {
            get
            {
                return (!String.IsNullOrEmpty(name));
            }
        }
        public void Authenticate(string userName)
        {
            name = userName;
        }

        public string IpAdress
        {
            get
            {
                if (communicationSocket != null)
                    return (communicationSocket.RemoteEndPoint as IPEndPoint).Address.ToString();
                return String.Empty;
            }
        }
        public string Port
        {
            get
            {
                if (communicationSocket != null)
                    return (communicationSocket.RemoteEndPoint as IPEndPoint).Port.ToString();
                return String.Empty;
            }
        }

        public Socket CommunicationSocket
        {
            get
            {
                return communicationSocket;
            }
        }

        public void StartThreadReceive()
        {
            threadReceive.Start();
        }

        public Group AddGroup(string name)
        {
            return groups.AddGroup(name);
        }

        public void RemoveGroup(string name)
        {
            groups.RemoveGroup(name);
        }

        public Group FindGroup(string groupName)
        {
            Group group = groups.Groups.FirstOrDefault(g => g.Name.Equals(groupName));
            return group;
        }

        public void Receive()
        {
            string message;
            byte[] buffer;
            if (communicationSocket != null)
            {
                while (communicationSocket.Connected)
                {
                    buffer = new byte[256];
                    communicationSocket.Receive(buffer);

                    message = Encoding.Default.GetString(buffer).Replace("\0", String.Empty);

                    messages.Enqueue(message);
                    if (!String.IsNullOrEmpty(message))
                    {
                        OnSomethingReceive(new EventArgs());
                    }


                }

            }
        }

        public string DequeueMessage()
        {
            return messages.Dequeue();
        }

        public string Serialize()
        {
            return name;
        }

        public static User Deserialize(string source)
        {
            User user = new User();
            user.name = source;
            return user;
        }

        public void OnSomethingReceive(EventArgs args)
        {
            if (SomethingReceived != null)
                SomethingReceived(this, args);
        }

        public override string ToString()
        {
            return name;
        }
    }
}
